﻿//////////////////////////////////////////////////////////////////////

#include "stdafx.h"
#include "DUIRadioBox.h"


int _RCWT(RECT rc)
	{
		return rc.right - rc.left;
}
int _RCHT(RECT rc)	
{return rc.bottom - rc.top;}


CDUIRadioBox::CDUIRadioBox()
{
	m_emState = CTRL_NORMAL;
	m_emOldState = CTRL_NORMAL;
	m_bIsCheck = FALSE;
	m_clTextNormal = RGB(250,250,250);
	m_clTextDisable = RGB(160,160,160);
	m_bTransBK = FALSE;
	m_bTracking = FALSE;
	m_pBackUpDC = NULL;
	m_pReaderDC = NULL;
	m_nAlpha = 0.0;
	m_nIndex = 0;
	m_bCheckedChg = 0;
	m_ltmAnimation = 0;
	m_bCheckedChg = FALSE;
	m_IsOpenAnim = TRUE;
	m_bIsFading = FALSE;
	m_bIsFirst = TRUE;

	m_pImage = new Gdiplus::Image((LPCTSTR)_T("D:\\_googlecodeSVN\\vasBubble\\vasBubble\\test.png"));
}

CDUIRadioBox::~CDUIRadioBox()
{
	if(m_pBackUpDC)
		delete m_pBackUpDC;
	m_pBackUpDC = NULL;
	if(m_pReaderDC)
		delete m_pReaderDC;
	m_pReaderDC = NULL;
}

BOOL CDUIRadioBox::SubclassWindow(HWND hwnd)
{
	BOOL bRet = CWindowImpl::SubclassWindow(hwnd);
	ModifyStyle(0, BS_OWNERDRAW|BS_AUTOCHECKBOX);
	return bRet;
}

int CDUIRadioBox::GetCheck()
{
	return m_bIsCheck;
}

void CDUIRadioBox::SetCheck(BOOL nState)
{
	if (nState && !m_bIsCheck)
	{
		m_bIsCheck = TRUE;
		m_bCheckedChg = TRUE;
		Invalidate(FALSE);
	}
	else if(!nState && m_bIsCheck)
	{
		m_bIsCheck = FALSE;
		m_bCheckedChg = TRUE;
		Invalidate(FALSE);
	}
}

void CDUIRadioBox::SetTextColor(COLORREF color,COLORREF colorDis/* = RGB(160,160,160)*/)
{
	m_clTextNormal = color;
	m_clTextDisable = colorDis;
	return ;
}

void CDUIRadioBox::GetTextColor(COLORREF& color,COLORREF& colorDis)
{
	color = m_clTextNormal;
	colorDis = m_clTextDisable;
	return ;
}

void CDUIRadioBox::SetTransparentBK(BOOL bTrans/*=TRUE*/)
{
	m_bTransBK = bTrans;
}

void CDUIRadioBox::DrawItem(LPDRAWITEMSTRUCT lpdis)
{
	CDCHandle dc = lpdis->hDC;	

	::GetWindowRect(m_hWnd, &m_rcRect);
	if(!m_pBackUpDC)
		m_pBackUpDC = new BackGDC(_RCWT(m_rcRect), _RCHT(m_rcRect));
	if(!m_pReaderDC)
	{
		m_pReaderDC = new BackGDC(_RCWT(m_rcRect), _RCHT(m_rcRect));
		{
			Gdiplus::Graphics graphics(m_pReaderDC->m_hdcBK);
			Gdiplus::SolidBrush bh(Gdiplus::Color(255, 78, 78, 78));
			graphics.FillRectangle(&bh, 0, 0, _RCWT(m_rcRect), _RCHT(m_rcRect));
		}
	}

	if(lpdis->itemState & ODS_DISABLED)
	{
		m_emState = CTRL_DISABLE;
		m_emOldState = CTRL_DISABLE;
		m_bCheckedChg = FALSE;
	}
	_DrawCtrl(m_pBackUpDC->m_hdcBK, m_bIsCheck, m_emState);

	if(m_bIsFirst)
	{
		m_bIsFirst = FALSE;
		BitBlt(dc.m_hDC, 0, 0, _RCWT(m_rcRect), _RCHT(m_rcRect), m_pBackUpDC->m_hdcBK, 0, 0, SRCCOPY);
		BitBlt(m_pReaderDC->m_hdcBK, 0, 0, _RCWT(m_rcRect), _RCHT(m_rcRect), m_pBackUpDC->m_hdcBK, 0, 0, SRCCOPY);
		m_emOldState = m_emState;
		return ;
	}

	if(m_IsOpenAnim && (m_emOldState != m_emState || m_bCheckedChg))
	{
		m_bCheckedChg = FALSE;
		_CloseFadeAnimation();
		m_ltmAnimation = SetTimer(CTRL_TM_RADIOBOX_ANIM, 22);
		m_emOldState = m_emState;
	}
	else
	{
		if(m_ltmAnimation)
			KillTimer(m_ltmAnimation);
		BitBlt(dc.m_hDC, 0, 0, _RCWT(m_rcRect), _RCHT(m_rcRect), m_pBackUpDC->m_hdcBK, 0, 0, SRCCOPY);
	}
}

void CDUIRadioBox::MeasureItem(LPMEASUREITEMSTRUCT lpMeasureItemStruct)
{
	lpMeasureItemStruct->itemHeight = 20;
}

void CDUIRadioBox::OnLButtonDown(UINT nFlags, CPoint pt)
{
	SetCapture();
	m_emState = CTRL_PUSHED;
	DefWindowProc();
}

void CDUIRadioBox::OnLButtonUp(UINT nFlags, CPoint pt)
{
 	CPoint	ptm;
 	CRect	rect;
 	GetCursorPos(&ptm);
 	::GetWindowRect(m_hWnd, &rect);
 	if (rect.PtInRect(ptm))
 	{
		m_emState = CTRL_HOVER;
 		DefWindowProc();
 	}
	else
		m_emState = CTRL_NORMAL;
 	ReleaseCapture();
}

LRESULT CDUIRadioBox::OnGetCheck(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
{
	return m_bIsCheck;
}

LRESULT CDUIRadioBox::OnSetCheck(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
{
	SetCheck(wParam);
	return 0;
}

void CDUIRadioBox::OnMouseMove(UINT nFlags, CPoint point)
{
	if (!m_bTracking)
	{
		TRACKMOUSEEVENT tme;
		tme.cbSize = sizeof(tme);
		tme.hwndTrack = m_hWnd;
		tme.dwFlags = TME_LEAVE|TME_HOVER;
		tme.dwHoverTime = 1;
		m_bTracking = _TrackMouseEvent(&tme);
		m_emState = CTRL_HOVER;

		RECT rc;
		GetClientRect(&rc);
		InvalidateRect(&rc, FALSE);
	}
}

void CDUIRadioBox::OnMouseLeave()
{
    m_bTracking = FALSE;
	m_emState = CTRL_NORMAL;

	RECT rc;
	GetClientRect(&rc);
	InvalidateRect(&rc, FALSE);
}

LRESULT CDUIRadioBox::OnEraseBkgnd(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
{
	RECT rc = {0, 0, _RCWT(m_rcRect), _RCHT(m_rcRect)};
	InvalidateRect(&rc, FALSE);
	return TRUE;
}

void CDUIRadioBox::_DrawCtrl(HDC hdc, BOOL IsCheck, emCtrlState m_emState)

{
	CRect rcRect;
	GetClientRect(&rcRect);

	Gdiplus::Graphics graphics(hdc);

	//------------ bg
	Gdiplus::SolidBrush bh(Gdiplus::Color(255, 78, 78, 78));
	graphics.FillRectangle(&bh, 0, 0, _RCWT(rcRect), _RCHT(rcRect));

	//------------ icon text
	int BmpWith = m_pImage->GetWidth();
	int BmpHigh = m_pImage->GetHeight();

	HFONT hFont = GetFont();
	HFONT hOldFont = (HFONT)::SelectObject(hdc, hFont);
	::SetBkMode(hdc, TRANSPARENT);

	Gdiplus::RectF destRect = Gdiplus::RectF(0, (rcRect.Height()-BmpHigh)/2, BmpWith, BmpHigh);
	switch(m_emState)
	{
	case CTRL_NORMAL:
		if(IsCheck)	graphics.DrawImage(m_pImage, destRect, BmpWith*1, 0, BmpWith, BmpHigh, Gdiplus::UnitPixel);
		else		graphics.DrawImage(m_pImage, destRect, BmpWith*0, 0, BmpWith, BmpHigh, Gdiplus::UnitPixel);
		rcRect.DeflateRect(destRect.GetRight()+2, 0, 0, 0);
		break;
	case CTRL_HOVER:
		if(IsCheck)	graphics.DrawImage(m_pImage, destRect, BmpWith*3, 0, BmpWith, BmpHigh, Gdiplus::UnitPixel);
		else		graphics.DrawImage(m_pImage, destRect, BmpWith*2, 0, BmpWith, BmpHigh, Gdiplus::UnitPixel);
		rcRect.DeflateRect(destRect.GetRight()+2, 0, 0, 0);
		break;
	case CTRL_PUSHED:
		if(IsCheck)	graphics.DrawImage(m_pImage, destRect, BmpWith*5, 0, BmpWith, BmpHigh, Gdiplus::UnitPixel);
		else		graphics.DrawImage(m_pImage, destRect, BmpWith*4, 0, BmpWith, BmpHigh, Gdiplus::UnitPixel);
		rcRect.DeflateRect(destRect.GetRight()+2, 0, 0, 0);
		break;
	case CTRL_DISABLE:
		if(IsCheck)	graphics.DrawImage(m_pImage, destRect, BmpWith*7, 0, BmpWith, BmpHigh, Gdiplus::UnitPixel);
		else		graphics.DrawImage(m_pImage, destRect, BmpWith*6, 0, BmpWith, BmpHigh, Gdiplus::UnitPixel);
		rcRect.DeflateRect(destRect.GetRight()+2, 0, 0, 0);
		break;
	default:
		break;
	}
}

LRESULT CDUIRadioBox::OnTimer(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
{
	switch(wParam)
	{
	case CTRL_TM_RADIOBOX_ANIM:
		_ReaderAnimation();
		break;
	default:
		break;
	}
	return TRUE;
}

void CDUIRadioBox::_ReaderAnimation()
{
	if(m_nIndex == 0)
	{
		m_bIsFading = TRUE;
 		m_nAlpha = 0.0;
		++m_nIndex;
		HDC hdc = ::GetDC(m_hWnd);
		BitBlt(hdc, 0, 0, _RCWT(m_rcRect), _RCHT(m_rcRect), m_pReaderDC->m_hdcBK, 0, 0, SRCCOPY);
		::ReleaseDC(m_hWnd, hdc);
		return ;
	}

	++m_nIndex;
	m_nAlpha += 255.0/11.0;

	BLENDFUNCTION bf;
	bf.BlendOp = AC_SRC_OVER;
	bf.BlendFlags = 0;
	bf.AlphaFormat = 0;
	bf.SourceConstantAlpha = m_nAlpha;

	AlphaBlend( m_pReaderDC->m_hdcBK, 0, 0, _RCWT(m_rcRect), _RCHT(m_rcRect), 
				m_pBackUpDC->m_hdcBK, 0, 0, _RCWT(m_rcRect), _RCHT(m_rcRect), bf);

	if(m_nIndex >= 11)
	{
		KillTimer(CTRL_TM_RADIOBOX_ANIM);
		m_ltmAnimation = 0;
		m_nIndex = 0;
		m_nAlpha = 0.0;
		StretchBlt( m_pReaderDC->m_hdcBK, 0, 0, _RCWT(m_rcRect), _RCHT(m_rcRect), 
					m_pBackUpDC->m_hdcBK, 0, 0, _RCWT(m_rcRect), _RCHT(m_rcRect), SRCCOPY);
		HDC hdc = ::GetDC(m_hWnd);
		BitBlt(hdc, 0, 0, _RCWT(m_rcRect), _RCHT(m_rcRect), m_pReaderDC->m_hdcBK, 0, 0, SRCCOPY);
		::ReleaseDC(m_hWnd, hdc);
		m_bIsFading = FALSE;
		return ;
	}
	//------------
	HDC hdc = ::GetDC(m_hWnd);
	BitBlt(hdc, 0, 0, _RCWT(m_rcRect), _RCHT(m_rcRect), m_pReaderDC->m_hdcBK, 0, 0, SRCCOPY);
	::ReleaseDC(m_hWnd, hdc);
}

void CDUIRadioBox::SetAnimationState(BOOL bState)
{
	m_IsOpenAnim = bState;
}

BOOL CDUIRadioBox::GetAnimationState()
{
	return m_IsOpenAnim;
}

void CDUIRadioBox::_CloseFadeAnimation()
{
	if(m_ltmAnimation)
	{
		KillTimer(CTRL_TM_RADIOBOX_ANIM);
		m_bIsFading = FALSE;
		m_nIndex = 0;
		m_ltmAnimation = 0;
	}
}

void CDUIRadioBox::OnEnable(BOOL bEnable)
{
	if(bEnable)
		m_emState = CTRL_NORMAL;
	else
		m_emState = CTRL_DISABLE;
	Invalidate(TRUE);
}